﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Medianamik.Core.Security
{
    public class Approbation
    {
        public Approbation(Guid objectId, string xml)
        {
            ObjectId = objectId;
            _xml = xml;

            _groupIds = ReadXml(Xml);
        }

        public Approbation(Guid objectId, IEnumerable<Guid> groupIds)
        {
            ObjectId = objectId;

            SetGroupIds(groupIds.ToList());
        }

        private static IList<Guid> ReadXml(string xml)
        {
            var xdoc = XDocument.Parse(xml);

            if (xdoc.Root == null || string.IsNullOrEmpty(xml))
                return new List<Guid>();

            return xdoc.Root.Elements("group")
                .Attributes("id")
                .Where(id => id != null)
                .Select(id => new Guid(id.Value))
                .ToList();
        }

        private static string ToXmlString(IEnumerable<Guid> groupIds)
        {
            var xdoc = new XDocument();
            var root = new XElement("groups");
            xdoc.Add(root);
            foreach (var id in groupIds)
            {
                var xele = new XElement("group");
                xele.Add(new XAttribute("id", id));
                root.Add(xele);
            }
            return xdoc.ToString(SaveOptions.DisableFormatting);
        }

        public Guid ObjectId { get; set; }

        // <groups><group id=""></groups>
        private string _xml;
        public string Xml
        {
            get { return _xml; }
        }

        private IList<Guid> _groupIds;
        private void SetGroupIds(IList<Guid> groupIds)
        {
            _groupIds = groupIds;
            _xml = ToXmlString(groupIds);
        }

        private bool _isOwned = true;
        public bool IsOwned
        {
            get { return _isOwned; }
            set { _isOwned = value; }
        }

        public int Level
        {
            get { return GetGroups().Count; }
        }

        private IList<Group> _groups;
        // Exclu les groupes inexistants
        public IList<Group> GetGroups()
        {
            if (_groupIds == null)
                return _groups;

            if (_groups == null)
            {
                _groups = new List<Group>();

                // Maintien l'ordre des groupIds
                foreach (var groupId in _groupIds)
                {
                    Guid id = groupId;
                    var group = SecurityManager.AllGroups.SingleOrDefault(x => x.ID == id);
                    // Sécurité si le groupe n'existe plus
                    if (group != null)
                        _groups.Add(group);
                }
            }

            return _groups;
        }
    }
}
